//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#ifndef __CMALLOC_H
#define __CMALLOC_H

#include <linknode.h>
//#include "winhack.h"
//#include <win32.h>

#ifndef STDMETHODCALLTYPE
#define STDMETHODCALLTYPE __stdcall
#endif

typedef Int64 TIME;

class CMalloc
{
public:
    CMalloc(){}
    virtual ~CMalloc(){}
public:
    virtual PVoid STDMETHODCALLTYPE Alloc(
            /* [in] */ size_t cb);

    virtual PVoid STDMETHODCALLTYPE Realloc(
            /* [in] */ PVoid pv,
            /* [in] */ size_t cb);

    virtual void STDMETHODCALLTYPE Free(
            /* [in] */ PVoid pv);

    size_t STDMETHODCALLTYPE GetSize(
            /* [in] */ PVoid pv);
};

class CMSpyMalloc : public CMalloc
{
public:
    CMSpyMalloc();
    ~CMSpyMalloc();
public:
    PVoid STDMETHODCALLTYPE Alloc(
            /* [in] */ size_t cb);

    PVoid STDMETHODCALLTYPE Realloc(
            /* [in] */ PVoid pv,
            /* [in] */ size_t cb);

    void STDMETHODCALLTYPE Free(
            /* [in] */ PVoid pv);
public:
    void PreAlloc(size_t UserSize);

    void PostAlloc(PVoid pMem, size_t UserSize);

    void PreFree(PVoid pMem);

    void DumpSpyList(TIME lasttime);

    void MemoryStatus();
#ifdef _MSVC
    void TrackStack(ULONG index);
#endif
public:
    // These variables are for heap memory statistic
    DoubleLinkNode *m_pMSpyNodeList;

    RTL_CRITICAL_SECTION m_Lock; // Lock

    unsigned int m_allocIdx;
    unsigned int m_nTotalHeapBlocks;
    unsigned int m_nMaxHeapBlocks;

    // Calculating the whole block not including header
    unsigned int m_nTotalHeapSize;
    unsigned int m_nMaxHeapSize;

    //the emulator max heap memory size
    unsigned int m_nheapLimitSize;

    // Recording the user allocating size
    // Because it's easy to debug
    unsigned int m_nMaxHeapBlockSize;
};

class CPreBChkMalloc : public CMalloc
{
public:
    virtual PVoid STDMETHODCALLTYPE Alloc(
            /* [in] */ size_t cb);

    virtual PVoid STDMETHODCALLTYPE Realloc(
            /* [in] */ PVoid pv,
            /* [in] */ size_t cb);

    virtual void STDMETHODCALLTYPE Free(
            /* [in] */ PVoid pv);
};

class CPostBChkMalloc : public CMalloc
{
public:
    virtual PVoid STDMETHODCALLTYPE Alloc(
            /* [in] */ size_t cb);

    virtual PVoid STDMETHODCALLTYPE Realloc(
            /* [in] */ PVoid pv,
            /* [in] */ size_t cb);

    virtual void STDMETHODCALLTYPE Free(
            /* [in] */ PVoid pv);
};

#define MALLOC         0
#define SPYMALLOC      1
#define PREBCHKMALLOC  2
#define POSTBCHKMALLOC 3

//#define HB_ALIGN    8            /* Allocation alignment                 */
//#define HB_ROUNDOFF (HB_ALIGN-1) /* Used to round up allocation size     */
//#define HB_MINBLOCKSIZE HB_ALIGN

/* RoundBlock returns an appropriate heap block size
 * (not including header) for a given byte count
*/
//INLINE UINT RoundBlock(UINT size)
//{
//    size = (size + HB_ROUNDOFF) & (~HB_ROUNDOFF);
//    if (size < HB_MINBLOCKSIZE) size = HB_MINBLOCKSIZE;
//    return size;
//}

#endif // __CMALLOC_H
